// Copyright Epic Games, Inc. All Rights Reserved.

#include "SHotPakerCookByTheBookSettings.h"

#include "DesktopPlatformModule.h"
#include "EditorStyleSet.h"
#include "Framework/Application/SlateApplication.h"
#include "SlateOptMacros.h"
#include "Widgets/Images/SImage.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Input/SCheckBox.h"
#include "Widgets/Input/SEditableTextBox.h"
#include "Widgets/Layout/SSeparator.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Views/SListView.h"

#include "Widgets/Shared/SHotPakerBuildConfigurationSelector.h"
#include "Widgets/Shared/SHotPakerFormLabel.h"
#include "Widgets/Cook/SHotPakerMapListRow.h"
#include "Widgets/Cook/SHotPakerCultureListRow.h"
#include "Widgets/Cook/SHotPakerCookedPlatforms.h"
#include "Widgets/Input/SHyperlink.h"
#include "Widgets/Layout/SExpandableArea.h"

#include "IDetailsView.h"
#include "Modules/ModuleManager.h"
#include "PropertyEditorModule.h"
#include "Models/HotPakToolType.h"
#include "HotPakerFileLib.h"
#include "PakUtils/ProcTaskThread.hpp"
#include "Widgets/Notifications/SNotificationList.h"
#include "Framework/Notifications/NotificationManager.h"
#include "Editor.h"
#include "EditorAnalytics.h"
#include "Async/Async.h"


#define LOCTEXT_NAMESPACE "SHotPakerCookByTheBookSettings"


/* SHotPakerCookByTheBookSettings structors
 *****************************************************************************/

SHotPakerCookByTheBookSettings::~SHotPakerCookByTheBookSettings()
{

}


/* SHotPakerCookByTheBookSettings interface
 *****************************************************************************/

BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SHotPakerCookByTheBookSettings::Construct(const FArguments& InArgs, const TSharedRef<FHotPakerModel>& InModel, bool InShowSimple)
{
	Model = InModel;

	ChildSlot
		[
			InShowSimple ? MakeSimpleWidget() : MakeComplexWidget()
		];


	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();
	if (SelectedProfile.IsValid())
	{
		SelectedProfile->OnProjectChanged().AddSP(this, &SHotPakerCookByTheBookSettings::HandleProfileProjectChanged);
	}

	ShowMapsChoice = EShowMapsChoices::ShowAllMaps;

	RefreshMapList();
	RefreshCultureList();
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION


/* SHotPakerCookByTheBookSettings implementation
 *****************************************************************************/

	BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
	TSharedRef<SWidget> SHotPakerCookByTheBookSettings::MakeComplexWidget()
{
	TSharedRef<SWidget> Widget = SNew(SVerticalBox)

		+ SVerticalBox::Slot()
		.AutoHeight()
		.MaxHeight(256.0f)
		[
			SNew(SBorder)
			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
		.Padding(8.0f)
		[
			SNew(SVerticalBox)

			+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SNew(SHotPakerFormLabel)
			.ErrorToolTipText(NSLOCTEXT("HotPakerBuildValidation", "NoCookedPlatformSelectedError", "At least one Platform must be selected when cooking by the book."))
		.ErrorVisibility(this, &SHotPakerCookByTheBookSettings::HandleValidationErrorIconVisibility, ELauncherProfileValidationErrors::NoPlatformSelected)
		.LabelText(LOCTEXT("CookedPlatformsLabel", "Cooked Platforms:"))
		]

	+ SVerticalBox::Slot()
		.FillHeight(1.0)
		.Padding(0.0f, 2.0f, 0.0f, 0.0f)
		[
			SNew(SHotPakerCookedPlatforms, Model.ToSharedRef())
		]
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.MaxHeight(256.0f)
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SBorder)
			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
		.Padding(8.0f)
		[
			SNew(SVerticalBox)

			+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SNew(SHotPakerFormLabel)
			.ErrorToolTipText(NSLOCTEXT("HotPakerBuildValidation", "NoCookedCulturesSelectedError", "At least one Culture must be selected when cooking by the book."))
		.ErrorVisibility(this, &SHotPakerCookByTheBookSettings::HandleValidationErrorIconVisibility, ELauncherProfileValidationErrors::NoCookedCulturesSelected)
		.LabelText(LOCTEXT("CookedCulturesLabel", "Cooked Cultures:"))
		]

	+ SVerticalBox::Slot()
		.FillHeight(1.0)
		.Padding(0.0f, 2.0f, 0.0f, 0.0f)
		[
			// culture menu
			SAssignNew(CultureListView, SListView<TSharedPtr<FString> >)
			.HeaderRow
			(
				SNew(SHeaderRow)
				.Visibility(EVisibility::Collapsed)

				+ SHeaderRow::Column("Culture")
				.DefaultLabel(LOCTEXT("CultureListMapNameColumnHeader", "Culture"))
				.FillWidth(1.0f)
			)
		.ItemHeight(16.0f)
		.ListItemsSource(&CultureList)
		.OnGenerateRow(this, &SHotPakerCookByTheBookSettings::HandleCultureListViewGenerateRow)
		.SelectionMode(ESelectionMode::None)
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 6.0f, 0.0f, 4.0f)
		[
			SNew(SSeparator)
			.Orientation(Orient_Horizontal)
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
		.FillWidth(1.0f)
		.HAlign(HAlign_Right)
		[
			SNew(STextBlock)
			.Text(LOCTEXT("SelectLabel", "Select:"))
		]

	+ SHorizontalBox::Slot()
		.AutoWidth()
		.Padding(8.0f, 0.0f)
		[
			// all cultures hyper link
			SNew(SHyperlink)
			.OnNavigate(this, &SHotPakerCookByTheBookSettings::HandleAllCulturesHyperlinkNavigate, true)
		.Text(LOCTEXT("AllPlatformsHyperlinkLabel", "All"))
		.ToolTipText(LOCTEXT("AllPlatformsButtonTooltip", "Select all available platforms."))
		.Visibility(this, &SHotPakerCookByTheBookSettings::HandleAllCulturesHyperlinkVisibility)
		]

	+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			// no cultures hyper link
			SNew(SHyperlink)
			.OnNavigate(this, &SHotPakerCookByTheBookSettings::HandleAllCulturesHyperlinkNavigate, false)
		.Text(LOCTEXT("NoCulturesHyperlinkLabel", "None"))
		.ToolTipText(LOCTEXT("NoCulturesHyperlinkTooltip", "Deselect all platforms."))
		.Visibility(this, &SHotPakerCookByTheBookSettings::HandleAllCulturesHyperlinkVisibility)
		]
		]
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.MaxHeight(256.0f)
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SBorder)
			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
		.Padding(8.0f)
		[
			SNew(SVerticalBox)

			+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SNew(SHotPakerFormLabel)
			.LabelText(LOCTEXT("CookedMapsLabel", "Cooked Maps:"))
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f)
		.VAlign(VAlign_Center)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			// all maps radio button
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleShowCheckBoxIsChecked, EShowMapsChoices::ShowAllMaps)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleShowCheckBoxCheckStateChanged, EShowMapsChoices::ShowAllMaps)
		.Style(FEditorStyle::Get(), "RadioButton")
		[
			SNew(STextBlock)
			.Text(LOCTEXT("AllMapsCheckBoxText", "Show all"))
		]
		]

	+ SHorizontalBox::Slot()
		.FillWidth(1.0f)
		.Padding(8.0f, 0.0f, 0.0f, 0.0f)
		[
			// cooked maps radio button
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleShowCheckBoxIsChecked, EShowMapsChoices::ShowCookedMaps)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleShowCheckBoxCheckStateChanged, EShowMapsChoices::ShowCookedMaps)
		.Style(FEditorStyle::Get(), "RadioButton")
		[
			SNew(STextBlock)
			.Text(LOCTEXT("CookedMapsCheckBoxText", "Show cooked"))
		]
		]
		]

	+ SVerticalBox::Slot()
		.FillHeight(1.0)
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// map list
			SAssignNew(MapListView, SListView<TSharedPtr<FString> >)
			.HeaderRow
			(
				SNew(SHeaderRow)
				.Visibility(EVisibility::Collapsed)

				+ SHeaderRow::Column("MapName")
				.DefaultLabel(LOCTEXT("MapListMapNameColumnHeader", "Map"))
				.FillWidth(1.0f)
			)
		.ItemHeight(16.0f)
		.ListItemsSource(&MapList)
		.OnGenerateRow(this, &SHotPakerCookByTheBookSettings::HandleMapListViewGenerateRow)
		.SelectionMode(ESelectionMode::None)
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SNew(SHorizontalBox)
			.Visibility(this, &SHotPakerCookByTheBookSettings::HandleNoMapSelectedBoxVisibility)

		+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			SNew(SImage)
			.Image(FEditorStyle::GetBrush(TEXT("Icons.Warning")))
		]

	+ SHorizontalBox::Slot()
		.AutoWidth()
		.Padding(4.0f, 0.0f)
		.VAlign(VAlign_Center)
		[
			SNew(STextBlock)
			.Text(this, &SHotPakerCookByTheBookSettings::HandleNoMapsTextBlockText)
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 6.0f, 0.0f, 4.0f)
		[
			SNew(SSeparator)
			.Orientation(Orient_Horizontal)
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.VAlign(VAlign_Center)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
		.FillWidth(1.0f)
		.HAlign(HAlign_Right)
		[
			SNew(STextBlock)
			.Text(LOCTEXT("SelectLabel", "Select:"))
		.Visibility(this, &SHotPakerCookByTheBookSettings::HandleMapSelectionHyperlinkVisibility)
		]

	+ SHorizontalBox::Slot()
		.AutoWidth()
		.Padding(8.0f, 0.0f)
		[
			// all maps hyper link
			SNew(SHyperlink)
			.OnNavigate(this, &SHotPakerCookByTheBookSettings::HandleAllMapsHyperlinkNavigate, true)
		.Text(LOCTEXT("AllMapsHyperlinkLabel", "All"))
		.ToolTipText(LOCTEXT("AllMapsHyperlinkTooltip", "Select all available maps."))
		.Visibility(this, &SHotPakerCookByTheBookSettings::HandleMapSelectionHyperlinkVisibility)
		]

	+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			// no maps hyper link
			SNew(SHyperlink)
			.OnNavigate(this, &SHotPakerCookByTheBookSettings::HandleAllMapsHyperlinkNavigate, false)
		.Text(LOCTEXT("NoMapsHyperlinkLabel", "None"))
		.ToolTipText(LOCTEXT("NoMapsHyperlinkTooltip", "Deselect all maps."))
		.Visibility(this, &SHotPakerCookByTheBookSettings::HandleMapSelectionHyperlinkVisibility)
		]
		]
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SExpandableArea)
			.AreaTitle(LOCTEXT("PatchingAreaTitle", "Release / DLC / Patching Settings"))
		.InitiallyCollapsed(true)
		.Padding(8.0f)
		.BodyContent()
		[
			SNew(SVerticalBox)

			//////////////////////////////////////////////////////////////////////////
			// create release version options
		+SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// unreal pak check box
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleCreateReleaseVersionCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleCreateReleaseVersionCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("CreateReleaseVersionCheckBoxTooltip", "Create a release version of the game for distribution."))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("CreateReleaseVersionBoxText", "Create a release version of the game for distribution."))
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SHotPakerFormLabel)
			.LabelText(LOCTEXT("CreateReleaseVersionTextBoxLabel", "Name of the new release to create."))
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0, 4.0, 0.0, 0.0)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
		.FillWidth(1.0)
		.Padding(0.0, 0.0, 0.0, 3.0)
		[
			// repository path text box
			SNew(SEditableTextBox)
			.ToolTipText(LOCTEXT("CreateReleaseVersionTextBoxTooltip", "Name of the new release to create."))
		.Text(this, &SHotPakerCookByTheBookSettings::HandleCreateReleaseVersionNameTextBlockText)
		.OnTextCommitted(this, &SHotPakerCookByTheBookSettings::HandleCreateReleaseVersionNameCommitted)
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SHotPakerFormLabel)
			.ToolTipText(LOCTEXT("BasedOnReleaseVersionTextBoxToolTip", "The release version which this DLC / Patch / Next release is based on."))
		.LabelText(LOCTEXT("BasedOnReleaseVersionTextBoxLabel", "Release version this is based on."))
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0, 4.0, 0.0, 0.0)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
		.FillWidth(1.0)
		.Padding(0.0, 0.0, 0.0, 3.0)
		[
			// repository path text box
			SNew(SEditableTextBox)
			.ToolTipText(LOCTEXT("NextReleaseVersionTextBoxTooltip", "Release version to base the next release / DLC / patch on."))
		.Text(this, &SHotPakerCookByTheBookSettings::HandleBasedOnReleaseVersionNameTextBlockText)
		.OnTextCommitted(this, &SHotPakerCookByTheBookSettings::HandleBasedOnReleaseVersionNameCommitted)
		]
		]

	// end create release version
	//////////////////////////////////////////////////////////////////////////

	// generate patch params
	+SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// unreal pak check box
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleGeneratePatchCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleGeneratePatchCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("GeneratePatchCheckBoxTooltip", "If checked, content will be diffed against source content and only changed files will be included in new pak"))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("GeneratePatchCheckBoxText", "Generate patch"))
		]
		]

	// end generate patch options
	//////////////////////////////////////////////////////////////////////////

	// generate dlc options
	+SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// unreal pak check box
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleBuildDLCCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleBuildDLCCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("BuildDLCCheckBoxTooltip", "If checked, DLC will be built without the content released with the original game."))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("BuildDLCCheckBoxText", "Build DLC"))
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SHotPakerFormLabel)
			.LabelText(LOCTEXT("DLCNameTextBoxLabel", "Name of the DLC to build."))
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0, 4.0, 0.0, 0.0)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
		.FillWidth(1.0)
		.Padding(0.0, 0.0, 0.0, 3.0)
		[
			// repository path text box
			SNew(SEditableTextBox)
			.ToolTipText(LOCTEXT("DLCNameTextBoxTooltip", "Name of DLC to build."))
		.Text(this, &SHotPakerCookByTheBookSettings::HandleDLCNameTextBlockText)
		.OnTextCommitted(this, &SHotPakerCookByTheBookSettings::HandleDLCNameCommitted)
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// unreal pak check box
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleDLCIncludeEngineContentCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleDLCIncludeEngineContentCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("HandleDLCIncludeEngineContentCheckBoxTooltip", "If checked, DLC will include engine content which was not included in original release, if not checked will error when accessing content from engine directory."))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("HandleDLCIncludeEngineContentCheckBoxText", "Include engine content"))
		]
		]

	// end generate dlc 
	//////////////////////////////////////////////////////////////////////////
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SExpandableArea)
			.AreaTitle(LOCTEXT("AdvancedAreaTitle", "Advanced Settings"))
		.InitiallyCollapsed(true)
		.Padding(8.0f)
		.BodyContent()
		[
			SNew(SVerticalBox)

			+ SVerticalBox::Slot()
		.AutoHeight()
		[
			// incremental cook check box
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleIncrementalCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleIncrementalCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("IncrementalCheckBoxTooltip", "If checked, only modified content will be cooked, resulting in much faster cooking times. It is recommended to enable this option whenever possible."))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("IncrementalCheckBoxText", "Iterative cooking: Only cook content modified from previous cook"))
		]
		]

	// disabled for now until this system is live
	/*+ SVerticalBox::Slot()
		.AutoHeight()
		[
			// incremental cook check box
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleSharedCookedBuildCheckBoxIsChecked)
			.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleSharedCookedBuildCheckBoxCheckStateChanged)
			.Padding(FMargin(4.0f, 0.0f))
			.ToolTipText(LOCTEXT("SharedCookedBuildCheckBoxToolTip", "Experimental: Use a build from the network to cook from."))
			.Content()
			[
				SNew(STextBlock)
				.Text(LOCTEXT("SharedCookedBuildCheckBoxText", "Iteratively cook from a pre packaged build located on the network"))
			]
		]*/

	+SVerticalBox::Slot()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		.AutoHeight()
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
		.FillWidth(1.0)
		.Padding(0.0, 0.0, 0.0, 3.0)
		[
			// repository path text box
			SNew(SEditableTextBox)
			.ToolTipText(LOCTEXT("NextReleaseVersionTextBoxTooltip", "Release version to base the next release / DLC / patch on."))
		.Text(this, &SHotPakerCookByTheBookSettings::HandleBasedOnReleaseVersionNameTextBlockText)
		.OnTextCommitted(this, &SHotPakerCookByTheBookSettings::HandleBasedOnReleaseVersionNameCommitted)
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// stage base release pak files check box
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleStageBaseReleasePaksCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleStageBaseReleasePaksCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("StageBaseReleasePaksCheckBoxTooltip", "If checked, unchanged pak files present in the base release version will be staged."))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("StageBaseReleasePaksCheckBoxText", "Stage base release pak files"))
		]
		]

	// generate patch params
	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// unreal pak check box
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleCompressedCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleCompressedCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("CompressedCheckboxToolTip", "If checked, content will be generated compressed.  These will be smaller but potentially take longer to load"))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("CompressedCheckBoxText", "Compress content"))
		]
		]

	// generate new patch level params
	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleAddPatchLevelCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleAddPatchLevelCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("AddPatchLevelCheckBoxTooltip", "If checked, a new numbered pak will be generated with patch content"))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("AddPatchLevelCheckBoxText", "Add a new patch tier"))
		]
		]

	// generate dlc options
	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// incremental cook check box
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleUnversionedCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleUnversionedCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("UnversionedCheckBoxTooltip", "If checked, the version is assumed to be current at load. This is potentially dangerous, but results in smaller patch sizes."))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("UnversionedCheckBoxText", "Save packages without versions"))
		]
		]

	// multiprocess cooking options
	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SHotPakerFormLabel)
			.LabelText(LOCTEXT("MultiProcessCookerTextBoxLabel", "Num cookers to spawn:"))
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// cooker command line options
			SNew(SEditableTextBox)
			.ToolTipText(LOCTEXT("MultiProcessCookerTextBoxTooltip", "The number of cookers to spawn when we do a cook by the book."))
		.Text(this, &SHotPakerCookByTheBookSettings::HandleMultiProcessCookerTextBlockText)
		.OnTextCommitted(this, &SHotPakerCookByTheBookSettings::HandleMultiProcessCookerCommitted)
		]

	// unreal pak check box
	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// unreal pak check box
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleUnrealPakCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleUnrealPakCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("UnrealPakCheckBoxTooltip", "If checked, the content will be deployed as a single UnrealPak file instead of many separate files."))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("UnrealPakCheckBoxText", "Store all content in a single file (UnrealPak)"))
		]
		]

	+ SVerticalBox::Slot()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		.AutoHeight()
		[
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleEncryptIniFilesCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleEncryptIniFilesCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("EncryptIniFilesCheckboxToolTip", "If checked, ini files stored inside pak file will be encrypted."))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("EncryptIniFilesCheckBoxText", "Encrypt ini files (only with use pak file)"))
		]
		]

	// generate chunks check box
	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[

			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleGenerateChunksCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleGenerateChunksCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("GenerateChunksCheckBoxTooltip", "If checked, the content will be deployed as multiple UnrealPak files instead of many separate files."))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("GenerateChunksCheckBoxText", "Generate Chunks"))
		]
		]

	// don't include editor content
	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[

			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleDontIncludeEditorContentCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleDontIncludeEditorContentCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("DontIncludeEditorContentCheckBoxTooltip", "If checked the cooker will skip editor content and not include it in the build."))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("DontIncludeEditorContentCheckBoxText", "Don't Include editor content in the build"))
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			SNew(SExpandableArea)
			.AreaTitle(LOCTEXT("HttpChunkInstallSettingsAreaTitle", "Http Chunk Install Settings"))
		.InitiallyCollapsed(true)
		.Padding(FMargin(4.0f, 0.0f))
		.BodyContent()
		[
			SNew(SVerticalBox)

			+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// unreal pak check box
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleHttpChunkInstallCheckBoxIsChecked)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleHttpChunkInstallCheckBoxCheckStateChanged)
		.Padding(FMargin(4.0f, 0.0f))
		.ToolTipText(LOCTEXT("HttpChunkInstallCheckBoxTooltip", "If checked, the content will be split into multiple paks and stored as data that can be downloaded."))
		.Content()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("HttpChunkInstallCheckBoxText", "Create Http Chunk Install data"))
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("HttpChunkInstallDataPathLabel", "Http Chunk Install Data Path:"))
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0, 4.0, 0.0, 0.0)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
		.FillWidth(1.0)
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// repository path text box
			SAssignNew(HttpChunkInstallDirectoryTextBox, SEditableTextBox)
			.Text(this, &SHotPakerCookByTheBookSettings::HandleHtppChunkInstallDirectoryText)
		.OnTextCommitted(this, &SHotPakerCookByTheBookSettings::HandleHtppChunkInstallDirectoryTextCommitted)
		.OnTextChanged(this, &SHotPakerCookByTheBookSettings::HandleHtppChunkInstallDirectoryTextChanged)
		]

	+ SHorizontalBox::Slot()
		.AutoWidth()
		.HAlign(HAlign_Right)
		.Padding(4.0, 0.0, 0.0, 0.0)
		[
			// browse button
			SNew(SButton)
			.ContentPadding(FMargin(6.0, 2.0))
		.IsEnabled(true)
		.Text(LOCTEXT("BrowseButtonText", "Browse..."))
		.ToolTipText(LOCTEXT("BrowseButtonToolTip", "Browse for the Http Chunk Install Data directory"))
		.OnClicked(this, &SHotPakerCookByTheBookSettings::HandleHtppChunkInstallBrowseButtonClicked)
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			SNew(SHotPakerFormLabel)
			.LabelText(LOCTEXT("HttpChunkInstallReleaseTextBoxLabel", "Http Chunk Install Release Name:"))
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// cooker command line options
			SNew(SEditableTextBox)
			.ToolTipText(LOCTEXT("HttpChunkInstallReleaseTextBoxTooltip", "Name of this version of the Http Chunk Install data."))
		.Text(this, &SHotPakerCookByTheBookSettings::HandleHttpChunkInstallNameTextBlockText)
		.OnTextCommitted(this, &SHotPakerCookByTheBookSettings::HandleHtppChunkInstallNameCommitted)
		]
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 12.0f, 0.0f, 0.0f)
		[
			SNew(SHotPakerFormLabel)
			.LabelText(LOCTEXT("CookConfigurationSelectorLabel", "Cooker build configuration:"))
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// cooker build configuration selector
			SNew(SHotPakerBuildConfigurationSelector)
			.OnConfigurationSelected(this, &SHotPakerCookByTheBookSettings::HandleCookConfigurationSelectorConfigurationSelected)
		.Text(this, &SHotPakerCookByTheBookSettings::HandleCookConfigurationSelectorText)
		.ToolTipText(LOCTEXT("CookConfigurationToolTipText", "Sets the build configuration to use for the cooker commandlet."))
		]

	// additional cooker options text box
	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SHotPakerFormLabel)
			.LabelText(LOCTEXT("CookerOptionsTextBoxLabel", "Additional Cooker Options:"))
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// cooker command line options
			SNew(SEditableTextBox)
			.ToolTipText(LOCTEXT("CookerOptionsTextBoxTooltip", "Additional cooker command line parameters can be specified here."))
		.Text(this, &SHotPakerCookByTheBookSettings::HandleCookOptionsTextBlockText)
		.OnTextCommitted(this, &SHotPakerCookByTheBookSettings::HandleCookerOptionsCommitted)
		]
		]
		];

	return Widget;
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION


BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
TSharedRef<SWidget> SHotPakerCookByTheBookSettings::MakeSimpleWidget()
{
	CreateAdvancedSettingDetailView();

	TSharedRef<SWidget> Widget = SNew(SVerticalBox)

		+ SVerticalBox::Slot()
		.AutoHeight()
		.MaxHeight(256.0f)
		[
			SNew(SBorder)
			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
		.Padding(8.0f)
		[
			SNew(SVerticalBox)

			+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SNew(SHotPakerFormLabel)
			.ErrorToolTipText(NSLOCTEXT("HotPakerBuildValidation", "NoCookedPlatformSelectedError", "At least one Platform must be selected when cooking by the book."))
		.ErrorVisibility(this, &SHotPakerCookByTheBookSettings::HandleValidationErrorIconVisibility, ELauncherProfileValidationErrors::NoPlatformSelected)
		.LabelText(LOCTEXT("CookedPlatformsLabel", "Cooked Platforms:"))
		]

	+ SVerticalBox::Slot()
		.FillHeight(1.0)
		.Padding(0.0f, 2.0f, 0.0f, 0.0f)
		[
			SNew(SHotPakerCookedPlatforms, Model.ToSharedRef())
		]
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.MaxHeight(256.0f)
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SBorder)
			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
		.Padding(8.0f)
		[
			SNew(SVerticalBox)

			+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SNew(SHotPakerFormLabel)
			.LabelText(LOCTEXT("CookedMapsLabel", "Cooked Maps:"))
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f)
		.VAlign(VAlign_Center)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			// all maps radio button
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleShowCheckBoxIsChecked, EShowMapsChoices::ShowAllMaps)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleShowCheckBoxCheckStateChanged, EShowMapsChoices::ShowAllMaps)
		.Style(FEditorStyle::Get(), "RadioButton")
		[
			SNew(STextBlock)
			.Text(LOCTEXT("AllMapsCheckBoxText", "Show all"))
		]
		]

	+ SHorizontalBox::Slot()
		.FillWidth(1.0f)
		.Padding(8.0f, 0.0f, 0.0f, 0.0f)
		[
			// cooked maps radio button
			SNew(SCheckBox)
			.IsChecked(this, &SHotPakerCookByTheBookSettings::HandleShowCheckBoxIsChecked, EShowMapsChoices::ShowCookedMaps)
		.OnCheckStateChanged(this, &SHotPakerCookByTheBookSettings::HandleShowCheckBoxCheckStateChanged, EShowMapsChoices::ShowCookedMaps)
		.Style(FEditorStyle::Get(), "RadioButton")
		[
			SNew(STextBlock)
			.Text(LOCTEXT("CookedMapsCheckBoxText", "Show cooked"))
		]
		]
		]

	+ SVerticalBox::Slot()
		.FillHeight(1.0)
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// map list
			SAssignNew(MapListView, SListView<TSharedPtr<FString> >)
			.HeaderRow
			(
				SNew(SHeaderRow)
				.Visibility(EVisibility::Collapsed)

				+ SHeaderRow::Column("MapName")
				.DefaultLabel(LOCTEXT("MapListMapNameColumnHeader", "Map"))
				.FillWidth(1.0f)
			)
		.ItemHeight(16.0f)
		.ListItemsSource(&MapList)
		.OnGenerateRow(this, &SHotPakerCookByTheBookSettings::HandleMapListViewGenerateRow)
		.SelectionMode(ESelectionMode::None)
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SNew(SHorizontalBox)
			.Visibility(this, &SHotPakerCookByTheBookSettings::HandleNoMapSelectedBoxVisibility)

		+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			SNew(SImage)
			.Image(FEditorStyle::GetBrush(TEXT("Icons.Warning")))
		]

	+ SHorizontalBox::Slot()
		.AutoWidth()
		.Padding(4.0f, 0.0f)
		.VAlign(VAlign_Center)
		[
			SNew(STextBlock)
			.Text(this, &SHotPakerCookByTheBookSettings::HandleNoMapsTextBlockText)
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 6.0f, 0.0f, 4.0f)
		[
			SNew(SSeparator)
			.Orientation(Orient_Horizontal)
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.VAlign(VAlign_Center)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
		.FillWidth(1.0f)
		.HAlign(HAlign_Right)
		[
			SNew(STextBlock)
			.Text(LOCTEXT("SelectLabel", "Select:"))
		.Visibility(this, &SHotPakerCookByTheBookSettings::HandleMapSelectionHyperlinkVisibility)
		]

	+ SHorizontalBox::Slot()
		.AutoWidth()
		.Padding(8.0f, 0.0f)
		[
			// all maps hyper link
			SNew(SHyperlink)
			.OnNavigate(this, &SHotPakerCookByTheBookSettings::HandleAllMapsHyperlinkNavigate, true)
		.Text(LOCTEXT("AllMapsHyperlinkLabel", "All"))
		.ToolTipText(LOCTEXT("AllMapsHyperlinkTooltip", "Select all available maps."))
		.Visibility(this, &SHotPakerCookByTheBookSettings::HandleMapSelectionHyperlinkVisibility)
		]

	+ SHorizontalBox::Slot()
		.AutoWidth()
		[
			// no maps hyper link
			SNew(SHyperlink)
			.OnNavigate(this, &SHotPakerCookByTheBookSettings::HandleAllMapsHyperlinkNavigate, false)
		.Text(LOCTEXT("NoMapsHyperlinkLabel", "None"))
		.ToolTipText(LOCTEXT("NoMapsHyperlinkTooltip", "Deselect all maps."))
		.Visibility(this, &SHotPakerCookByTheBookSettings::HandleMapSelectionHyperlinkVisibility)
		]
		]
		]
		]


	+ SVerticalBox::Slot()
		.AutoHeight()
		.MaxHeight(256.0f)
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SBorder)
			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
		.Padding(8.0f)
		[
			SNew(SVerticalBox)

			+ SVerticalBox::Slot()
		.AutoHeight()
		[
			AdvancedSettingsView->AsShared()
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			SNew(STextBlock)
			.Text(LOCTEXT("AdvancedOptionsLabel", "AdvancedOptions"))
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			SAssignNew(AdvancedOptionsEditor, SEditableTextBox)
		]

		]

		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0f, 8.0f, 0.0f, 0.0f)
		[
			SNew(SOverlay)

			+ SOverlay::Slot()
		.HAlign(EHorizontalAlignment::HAlign_Right)
		[
			SNew(SButton)
			.OnClicked(this, &SHotPakerCookByTheBookSettings::StartCookAssets)
		.IsEnabled_Lambda([this]() { return StartCookAssetsEnabled(); })
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		[
			SNew(STextBlock)
			.Text(LOCTEXT("StartCookAssets", "StartCook"))
		]
		]
		]


	;

	AdvancedSettingsView->SetObject(CookAdvancedSettings);

	return Widget;
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION


void SHotPakerCookByTheBookSettings::RefreshCultureList()
{
	CultureList.Reset();

	TArray<FString> CultureNames;
	FInternationalization::Get().GetCultureNames(CultureNames);

	if (CultureNames.Num() > 0)
	{
		for (int32 Index = 0; Index < CultureNames.Num(); ++Index)
		{
			FString CultureName = CultureNames[Index];
			CultureList.Add(MakeShareable(new FString(CultureName)));
		}
	}

	if (CultureListView.IsValid())
	{
		CultureListView->RequestListRefresh();
	}
}


void SHotPakerCookByTheBookSettings::RefreshMapList()
{
	MapList.Reset();

	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		TArray<FString> AvailableMaps = FGameProjectHelper::GetAvailableMaps(SelectedProfile->GetProjectBasePath(), SelectedProfile->SupportsEngineMaps(), true);

		for (int32 AvailableMapIndex = 0; AvailableMapIndex < AvailableMaps.Num(); ++AvailableMapIndex)
		{
			FString& Map = AvailableMaps[AvailableMapIndex];

			if ((ShowMapsChoice == EShowMapsChoices::ShowAllMaps) || SelectedProfile->GetCookedMaps().Contains(Map))
			{
				MapList.Add(MakeShareable(new FString(Map)));
			}
		}
	}

	MapListView->RequestListRefresh();
}


/* SHotPakerCookByTheBookSettings callbacks
 *****************************************************************************/

EVisibility SHotPakerCookByTheBookSettings::HandleCulturesSettingsVisibility() const
{
	return EVisibility::Collapsed;
}

void SHotPakerCookByTheBookSettings::CreateAdvancedSettingDetailView()
{
	CookAdvancedSettings = GetMutableDefault<UCookAdvancedSettings>();

	// Create a property view
	FPropertyEditorModule& EditModule = FModuleManager::Get().GetModuleChecked<FPropertyEditorModule>("PropertyEditor");

	FDetailsViewArgs DetailsViewArgs;
	DetailsViewArgs.bUpdatesFromSelection = true;
	DetailsViewArgs.bLockable = true;
	DetailsViewArgs.NameAreaSettings = FDetailsViewArgs::ComponentsAndActorsUseNameArea;
	DetailsViewArgs.bCustomNameAreaLocation = false;
	DetailsViewArgs.bCustomFilterAreaLocation = true;
	DetailsViewArgs.DefaultsOnlyVisibility = EEditDefaultsOnlyNodeVisibility::Hide;

	AdvancedSettingsView = EditModule.CreateDetailView(DetailsViewArgs);;
}

FReply SHotPakerCookByTheBookSettings::StartCookAssets()
{
	ILauncherProfilePtr HotPakerProfile = Model->GetHotPakerProfile();

	if (HotPakerProfile.IsValid())
	{

		FString FullCommandParams = FString::Printf(TEXT("%s -run=cook -targetplatform"), *FPaths::ConvertRelativePathToFull(HotPakerProfile->GetProjectPath()));

		TArray<FString> TargetPlatforms = HotPakerProfile->GetCookedPlatforms();
		for (int i = 0; i < TargetPlatforms.Num(); ++i)
		{
			FullCommandParams += i == 0 ? FString::Printf(TEXT("=%s"), *TargetPlatforms[i]) : FString::Printf(TEXT("+%s"), *TargetPlatforms[i]);
		}

		if (!CookAdvancedSettings->bCookAll)
		{
			FullCommandParams += TEXT(" -map");
			TArray<FString> CookedMaps = HotPakerProfile->GetCookedMaps();
			for (int i = 0; i < CookedMaps.Num(); ++i)
			{
				FullCommandParams += i == 0 ? FString::Printf(TEXT("=%s"), *CookedMaps[i]) : FString::Printf(TEXT("+%s"), *CookedMaps[i]);
			}
		}

		if (CookAdvancedSettings->bCookIterate)
		{
			FullCommandParams += TEXT(" -iterate");
		}

		if (CookAdvancedSettings->bCookAll)
		{
			FullCommandParams += TEXT(" -CookAll");
		}

		if (CookAdvancedSettings->bCompressed)
		{
			FullCommandParams += TEXT(" -Compressed");
		}

		if (HotPakerProfile->GetCookedPlatforms().Num() == 1 && !CookAdvancedSettings->CookOutputDirectory.Path.IsEmpty())
		{
			FullCommandParams += FString::Printf(TEXT(" OutputDir=%s/%s"), *CookAdvancedSettings->CookOutputDirectory.Path, *HotPakerProfile->GetCookedPlatforms()[0]);
		}

		if (!AdvancedOptionsEditor->GetText().ToString().IsEmpty())
		{
			FString AdvancedOptionsLine = AdvancedOptionsEditor->GetText().ToString();
			FullCommandParams += FString::Printf(TEXT(" %s"), *AdvancedOptionsLine.Trim());
		}

		CookProcTaskThread = MakeShareable(new FProcTaskThread(TEXT("CookTask"), UHotPakerFileLib::GetUE4CmdBinary(), FullCommandParams));
		CookProcTaskThread->ProcBeginDelegate.AddRaw(this, &SHotPakerCookByTheBookSettings::HandleCookProcBegin);
		CookProcTaskThread->ProcSucceedDelegate.AddRaw(this, &SHotPakerCookByTheBookSettings::HandleCookProcSucceed);
		CookProcTaskThread->ProcFailedDelegate.AddRaw(this, &SHotPakerCookByTheBookSettings::HandleCookProcFailed);
		CookProcTaskThread->ProcResultDelegate.AddRaw(this, &SHotPakerCookByTheBookSettings::HandleCookProcResult);

		CookProcTaskThread->Execute();
	}

	return FReply::Handled();
}

bool SHotPakerCookByTheBookSettings::StartCookAssetsEnabled()
{
	if (CookProcTaskThread.IsValid())
		return false;

	ILauncherProfilePtr HotPakerProfile = Model->GetHotPakerProfile();

	if (HotPakerProfile.IsValid())
	{
		if (HotPakerProfile->GetCookedPlatforms().Num() == 0)
			return false;

		if (HotPakerProfile->GetCookedPlatforms().Num() > 1 && !CookAdvancedSettings->CookOutputDirectory.Path.IsEmpty())
			return false;

		if (HotPakerProfile->GetCookedMaps().Num() == 0 && !CookAdvancedSettings->bCookAll)
			return false;

	}
	else
		return false;

	return true;
}

void SHotPakerCookByTheBookSettings::HandleCookProcResult(FString OutputLog)
{
	if (OutputLog.Contains(TEXT("Error:")))
	{
		UE_LOG(LogTemp, Error, TEXT("%s"), *OutputLog);
	}
	else if (OutputLog.Contains(TEXT("Warning:")))
	{
		UE_LOG(LogTemp, Warning, TEXT("%s"), *OutputLog);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("%s"), *OutputLog);
	}
}

void SHotPakerCookByTheBookSettings::HandleCookProcBegin()
{
	AsyncTask(ENamedThreads::GameThread, [this]() {

		ILauncherProfilePtr HotPakerProfile = Model->GetHotPakerProfile();
		if (!HotPakerProfile.IsValid())
			return;

		FString TargetPlatforms;
		for (int i = 0; i < HotPakerProfile->GetCookedPlatforms().Num(); ++i)
		{
			TargetPlatforms += i == 0 ? HotPakerProfile->GetCookedPlatforms()[0] : FString::Printf(TEXT("+%s"), *HotPakerProfile->GetCookedPlatforms()[i]);
		}

		// create notification item
		FFormatNamedArguments Arguments;
		Arguments.Add(TEXT("Platform"), FText::FromString(TargetPlatforms));
		Arguments.Add(TEXT("TaskName"), FText::FromString(TEXT("CookTask")));
		FNotificationInfo Info(FText::Format(LOCTEXT("UatTaskInProgressNotification", "{TaskName} for {Platform}..."), Arguments));

		Info.Image = FEditorStyle::GetBrush(TEXT("MainFrame.CookContent"));
		Info.bFireAndForget = false;
		Info.FadeOutDuration = 0.0f;
		Info.ExpireDuration = 0.0f;
		Info.Hyperlink = FSimpleDelegate::CreateRaw(this, &SHotPakerCookByTheBookSettings::HandleUatHyperlinkNavigate);
		Info.HyperlinkText = LOCTEXT("ShowOutputLogHyperlink", "Show Output Log");
		Info.ButtonDetails.Add(
			FNotificationButtonInfo(
				LOCTEXT("UatTaskCancel", "Cancel"),
				LOCTEXT("UatTaskCancelToolTip", "Cancels execution of this task."),
				FSimpleDelegate::CreateRaw(this, &SHotPakerCookByTheBookSettings::HandleUatCancelButtonClicked),
				SNotificationItem::CS_Pending
			)
		);
		Info.ButtonDetails.Add(
			FNotificationButtonInfo(
				LOCTEXT("UatTaskDismiss", "Dismiss"),
				FText(),
				FSimpleDelegate::CreateRaw(this, &SHotPakerCookByTheBookSettings::HandleDismissButtonClicked),
				SNotificationItem::CS_Fail
			)
		);

		TSharedPtr<SNotificationItem> NotificationItem = FSlateNotificationManager::Get().AddNotification(Info);
		if (NotificationItemPtr.IsValid())
		{
			NotificationItemPtr.Pin().Get()->Fadeout();
		}

		if (!NotificationItem.IsValid())
		{
			return;
		}

		FEditorAnalytics::ReportEvent(TEXT("Editor.Cook.Start"), HotPakerProfile->GetCookedPlatforms()[0], false);

		NotificationItem->SetCompletionState(SNotificationItem::CS_Pending);

		// launch the packager
		NotificationItemPtr = NotificationItem;

		GEditor->PlayEditorSound(TEXT("/Engine/EditorSounds/Notifications/CompileStart_Cue.CompileStart_Cue"));
	}
	);
}

void SHotPakerCookByTheBookSettings::HandleCookProcSucceed()
{
	AsyncTask(ENamedThreads::GameThread, [this]()
	{
		TSharedPtr<SNotificationItem> NotificationItem = NotificationItemPtr.Pin();

		if (NotificationItem.IsValid())
		{
			NotificationItem->SetText(LOCTEXT("CookSuccessedNotification", "Cook Finished!"));
			NotificationItem->SetCompletionState(SNotificationItem::CS_Success);
			NotificationItem->ExpireAndFadeout();

			NotificationItemPtr.Reset();
		}

		CookProcTaskThread.Reset();

		GEditor->PlayEditorSound(TEXT("/Engine/EditorSounds/Notifications/CompileSuccess_Cue.CompileSuccess_Cue"));
	}
	);
}

void SHotPakerCookByTheBookSettings::HandleCookProcFailed()
{
	AsyncTask(ENamedThreads::GameThread, [this]()
	{
		TSharedPtr<SNotificationItem> NotificationItem = NotificationItemPtr.Pin();

		if (NotificationItem.IsValid())
		{
			NotificationItem->SetText(LOCTEXT("CookFaildNotification", "Cook Faild!"));
			NotificationItem->SetCompletionState(SNotificationItem::CS_Fail);
			NotificationItem->ExpireAndFadeout();

			NotificationItemPtr.Reset();
		}

		CookProcTaskThread.Reset();

		GEditor->PlayEditorSound(TEXT("/Engine/EditorSounds/Notifications/CompileFailed_Cue.CompileFailed_Cue"));
	}
	);
}

void SHotPakerCookByTheBookSettings::HandleUatHyperlinkNavigate()
{
	FGlobalTabmanager::Get()->InvokeTab(FName("OutputLog"));
}

void SHotPakerCookByTheBookSettings::HandleUatCancelButtonClicked()
{
	if (CookProcTaskThread.IsValid())
	{
		CookProcTaskThread->Cancel();
	}
}

void SHotPakerCookByTheBookSettings::HandleDismissButtonClicked()
{

}

void SHotPakerCookByTheBookSettings::HandleAllCulturesHyperlinkNavigate(bool AllPlatforms)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (AllPlatforms)
		{
			TArray<FString> CultureNames;
			FInternationalization::Get().GetCultureNames(CultureNames);

			for (int32 ExtensionIndex = 0; ExtensionIndex < CultureNames.Num(); ++ExtensionIndex)
			{
				SelectedProfile->AddCookedCulture(CultureNames[ExtensionIndex]);
			}
		}
		else
		{
			SelectedProfile->ClearCookedCultures();
		}
	}
}


EVisibility SHotPakerCookByTheBookSettings::HandleAllCulturesHyperlinkVisibility() const
{
	TArray<FString> CultureNames;
	FInternationalization::Get().GetCultureNames(CultureNames);

	if (CultureNames.Num() > 1)
	{
		return EVisibility::Visible;
	}

	return EVisibility::Collapsed;
}


void SHotPakerCookByTheBookSettings::HandleAllMapsHyperlinkNavigate(bool AllPlatforms)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (AllPlatforms)
		{
			TArray<FString> AvailableMaps = FGameProjectHelper::GetAvailableMaps(SelectedProfile->GetProjectBasePath(), SelectedProfile->SupportsEngineMaps(), false);

			for (int32 AvailableMapIndex = 0; AvailableMapIndex < AvailableMaps.Num(); ++AvailableMapIndex)
			{
				SelectedProfile->AddCookedMap(AvailableMaps[AvailableMapIndex]);
			}
		}
		else
		{
			SelectedProfile->ClearCookedMaps();
		}
	}
}


EVisibility SHotPakerCookByTheBookSettings::HandleMapSelectionHyperlinkVisibility() const
{
	if (MapList.Num() > 1)
	{
		return EVisibility::Visible;
	}

	return EVisibility::Collapsed;
}


void SHotPakerCookByTheBookSettings::HandleCookConfigurationSelectorConfigurationSelected(EBuildConfiguration Configuration)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetCookConfiguration(Configuration);
	}
}


FText SHotPakerCookByTheBookSettings::HandleCookConfigurationSelectorText() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		return FText::FromString(LexToString(SelectedProfile->GetCookConfiguration()));
	}

	return FText::GetEmpty();
}


void SHotPakerCookByTheBookSettings::HandleIncrementalCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetIncrementalCooking(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleIncrementalCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->IsCookingIncrementally())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}


void SHotPakerCookByTheBookSettings::HandleSharedCookedBuildCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetIterateSharedCookedBuild(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleSharedCookedBuildCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->IsIterateSharedCookedBuild())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}


void SHotPakerCookByTheBookSettings::HandleCompressedCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetCompressed(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleCompressedCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->IsCompressed())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}


void SHotPakerCookByTheBookSettings::HandleEncryptIniFilesCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetEncryptingIniFiles(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleEncryptIniFilesCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->IsEncryptingIniFiles())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}


TSharedRef<ITableRow> SHotPakerCookByTheBookSettings::HandleMapListViewGenerateRow(TSharedPtr<FString> InItem, const TSharedRef<STableViewBase>& OwnerTable)
{
	return SNew(SHotPakerMapListRow, Model.ToSharedRef())
		.MapName(InItem)
		.OwnerTableView(OwnerTable);
}


TSharedRef<ITableRow> SHotPakerCookByTheBookSettings::HandleCultureListViewGenerateRow(TSharedPtr<FString> InItem, const TSharedRef<STableViewBase>& OwnerTable)
{
	return SNew(SHotPakerCultureListRow, Model.ToSharedRef())
		.CultureName(InItem)
		.OwnerTableView(OwnerTable);
}


EVisibility SHotPakerCookByTheBookSettings::HandleNoMapSelectedBoxVisibility() const
{
	if (MapList.Num() == 0)
	{
		return EVisibility::Visible;
	}

	return EVisibility::Collapsed;
}


FText SHotPakerCookByTheBookSettings::HandleNoMapsTextBlockText() const
{
	if (MapList.Num() == 0)
	{
		if (ShowMapsChoice == EShowMapsChoices::ShowAllMaps)
		{
			return LOCTEXT("NoMapsFoundText", "No available maps were found.");
		}
		else if (ShowMapsChoice == EShowMapsChoices::ShowCookedMaps)
		{
			return LOCTEXT("NoMapsSelectedText", "No map selected. Only startup packages will be cooked!");
		}
	}

	return FText();
}


void SHotPakerCookByTheBookSettings::HandleProfileManagerProfileSelected(const ILauncherProfilePtr& SelectedProfile, const ILauncherProfilePtr& PreviousProfile)
{
	if (PreviousProfile.IsValid())
	{
		PreviousProfile->OnProjectChanged().RemoveAll(this);
	}
	if (SelectedProfile.IsValid())
	{
		SelectedProfile->OnProjectChanged().AddSP(this, &SHotPakerCookByTheBookSettings::HandleProfileProjectChanged);
	}
	RefreshMapList();
	RefreshCultureList();
}


void SHotPakerCookByTheBookSettings::HandleProfileProjectChanged()
{
	RefreshMapList();
	RefreshCultureList();
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleShowCheckBoxIsChecked(EShowMapsChoices::Type Choice) const
{
	if (ShowMapsChoice == Choice)
	{
		return ECheckBoxState::Checked;
	}

	return ECheckBoxState::Unchecked;
}


void SHotPakerCookByTheBookSettings::HandleShowCheckBoxCheckStateChanged(ECheckBoxState NewState, EShowMapsChoices::Type Choice)
{
	if (NewState == ECheckBoxState::Checked)
	{
		ShowMapsChoice = Choice;
		RefreshMapList();
	}
}


void SHotPakerCookByTheBookSettings::HandleUnversionedCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetUnversionedCooking((NewState == ECheckBoxState::Checked));
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleUnversionedCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->IsCookingUnversioned())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}


EVisibility SHotPakerCookByTheBookSettings::HandleValidationErrorIconVisibility(ELauncherProfileValidationErrors::Type Error) const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->HasValidationError(Error))
		{
			return EVisibility::Visible;
		}
	}

	return EVisibility::Hidden;
}


FText SHotPakerCookByTheBookSettings::HandleCookOptionsTextBlockText() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	FText result;

	if (SelectedProfile.IsValid())
	{
		result = FText::FromString(SelectedProfile->GetCookOptions());
	}

	return result;
}


void SHotPakerCookByTheBookSettings::HandleCookerOptionsCommitted(const FText& NewText, ETextCommit::Type CommitType)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		FString useOptions = NewText.ToString();
		switch (CommitType)
		{
		case ETextCommit::Default:
		case ETextCommit::OnCleared:
			useOptions = TEXT("");
			break;
		default:
			break;
		}
		SelectedProfile->SetCookOptions(useOptions);
	}
}


FText SHotPakerCookByTheBookSettings::HandleMultiProcessCookerTextBlockText() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	FText result;

	if (SelectedProfile.IsValid())
	{
		result = FText::FromString(FString::FromInt(SelectedProfile->GetNumCookersToSpawn()));
	}

	return result;
}


void SHotPakerCookByTheBookSettings::HandleMultiProcessCookerCommitted(const FText& NewText, ETextCommit::Type CommitType)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		int32 NumCookersToSpawn = FCString::Atoi(*NewText.ToString());
		switch (CommitType)
		{
		case ETextCommit::Default:
		case ETextCommit::OnCleared:
			NumCookersToSpawn = 0;
			break;
		default:
			break;
		}
		SelectedProfile->SetNumCookersToSpawn(NumCookersToSpawn);
	}
}


void SHotPakerCookByTheBookSettings::HandleUnrealPakCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetDeployWithUnrealPak(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleUnrealPakCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->IsPackingWithUnrealPak())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}


void SHotPakerCookByTheBookSettings::HandleGeneratePatchCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetGeneratePatch(NewState == ECheckBoxState::Checked);
	}
}


void SHotPakerCookByTheBookSettings::HandleAddPatchLevelCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetAddPatchLevel(NewState == ECheckBoxState::Checked);
	}
}


void SHotPakerCookByTheBookSettings::HandleStageBaseReleasePaksCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetStageBaseReleasePaks(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleGeneratePatchCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->IsGeneratingPatch())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}

// Callback for determining the checked state of the 'AddPatchLevel' check box.
ECheckBoxState SHotPakerCookByTheBookSettings::HandleAddPatchLevelCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->ShouldAddPatchLevel())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleStageBaseReleasePaksCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->ShouldStageBaseReleasePaks())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}


void SHotPakerCookByTheBookSettings::HandleCreateReleaseVersionCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetCreateReleaseVersion(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleCreateReleaseVersionCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->IsCreatingReleaseVersion())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}


FText SHotPakerCookByTheBookSettings::HandleCreateReleaseVersionNameTextBlockText() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	FText result;

	if (SelectedProfile.IsValid())
	{
		result = FText::FromString(SelectedProfile->GetCreateReleaseVersionName());
	}

	return result;
}


void SHotPakerCookByTheBookSettings::HandleCreateReleaseVersionNameCommitted(const FText& NewText, ETextCommit::Type CommitType)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetCreateReleaseVersionName(NewText.ToString());
	}

}


FText SHotPakerCookByTheBookSettings::HandleBasedOnReleaseVersionNameTextBlockText() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	FText result;

	if (SelectedProfile.IsValid())
	{
		result = FText::FromString(SelectedProfile->GetBasedOnReleaseVersionName());
	}

	return result;
}


void SHotPakerCookByTheBookSettings::HandleBasedOnReleaseVersionNameCommitted(const FText& NewText, ETextCommit::Type CommitType)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetBasedOnReleaseVersionName(NewText.ToString());
	}

}


FText SHotPakerCookByTheBookSettings::HandleDLCNameTextBlockText() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	FText result;

	if (SelectedProfile.IsValid())
	{
		result = FText::FromString(SelectedProfile->GetDLCName());
	}

	return result;
}


void SHotPakerCookByTheBookSettings::HandleDLCNameCommitted(const FText& NewText, ETextCommit::Type CommitType)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetDLCName(NewText.ToString());
	}
}


void SHotPakerCookByTheBookSettings::HandleBuildDLCCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetCreateDLC(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleBuildDLCCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->IsCreatingDLC())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}


FReply SHotPakerCookByTheBookSettings::HandleHtppChunkInstallBrowseButtonClicked()
{
	IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
	if (DesktopPlatform)
	{
		TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().FindWidgetWindow(AsShared());
		void* ParentWindowHandle = (ParentWindow.IsValid() && ParentWindow->GetNativeWindow().IsValid()) ? ParentWindow->GetNativeWindow()->GetOSWindowHandle() : nullptr;

		FString FolderName;
		const bool bFolderSelected = DesktopPlatform->OpenDirectoryDialog(
			ParentWindowHandle,
			LOCTEXT("RepositoryBrowseTitle", "Choose a repository location").ToString(),
			HttpChunkInstallDirectoryTextBox->GetText().ToString(),
			FolderName
		);

		if (bFolderSelected)
		{
			if (!FolderName.EndsWith(TEXT("/")))
			{
				FolderName += TEXT("/");
			}

			HttpChunkInstallDirectoryTextBox->SetText(FText::FromString(FolderName));
			ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

			if (SelectedProfile.IsValid())
			{
				SelectedProfile->SetHttpChunkDataDirectory(FolderName);
			}
		}
	}

	return FReply::Handled();
}


FText SHotPakerCookByTheBookSettings::HandleHtppChunkInstallDirectoryText() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		return FText::FromString(SelectedProfile->GetHttpChunkDataDirectory());
	}

	return FText::GetEmpty();
}


void SHotPakerCookByTheBookSettings::HandleHtppChunkInstallDirectoryTextChanged(const FText& InText)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetHttpChunkDataDirectory(InText.ToString());
	}
}


void SHotPakerCookByTheBookSettings::HandleHtppChunkInstallDirectoryTextCommitted(const FText& InText, ETextCommit::Type CommitInfo)
{
	if (CommitInfo == ETextCommit::OnEnter)
	{
		ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

		if (SelectedProfile.IsValid())
		{
			SelectedProfile->SetHttpChunkDataDirectory(InText.ToString());
		}
	}
}


void SHotPakerCookByTheBookSettings::HandleHttpChunkInstallCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();
	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetGenerateHttpChunkData(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleHttpChunkInstallCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();
	if (SelectedProfile.IsValid())
	{
		return SelectedProfile->IsGenerateHttpChunkData() ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
	}

	return ECheckBoxState::Unchecked;
}


FText SHotPakerCookByTheBookSettings::HandleHttpChunkInstallNameTextBlockText() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		return FText::FromString(SelectedProfile->GetHttpChunkDataReleaseName());
	}

	return FText();
}


void SHotPakerCookByTheBookSettings::HandleHtppChunkInstallNameCommitted(const FText& NewText, ETextCommit::Type CommitType)
{
	if (CommitType == ETextCommit::OnEnter)
	{
		ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

		if (SelectedProfile.IsValid())
		{
			SelectedProfile->SetHttpChunkDataReleaseName(NewText.ToString());
		}
	}
}


void SHotPakerCookByTheBookSettings::HandleDLCIncludeEngineContentCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetDLCIncludeEngineContent(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleDLCIncludeEngineContentCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		if (SelectedProfile->IsDLCIncludingEngineContent())
		{
			return ECheckBoxState::Checked;
		}
	}

	return ECheckBoxState::Unchecked;
}


void SHotPakerCookByTheBookSettings::HandleGenerateChunksCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetGenerateChunks(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleGenerateChunksCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();
	if (SelectedProfile.IsValid())
	{
		return SelectedProfile->IsGeneratingChunks() ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
	}
	return ECheckBoxState::Unchecked;
}


void SHotPakerCookByTheBookSettings::HandleDontIncludeEditorContentCheckBoxCheckStateChanged(ECheckBoxState NewState)
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();

	if (SelectedProfile.IsValid())
	{
		SelectedProfile->SetSkipCookingEditorContent(NewState == ECheckBoxState::Checked);
	}
}


ECheckBoxState SHotPakerCookByTheBookSettings::HandleDontIncludeEditorContentCheckBoxIsChecked() const
{
	ILauncherProfilePtr SelectedProfile = Model->GetHotPakerProfile();
	if (SelectedProfile.IsValid())
	{
		return SelectedProfile->GetSkipCookingEditorContent() ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
	}
	return ECheckBoxState::Unchecked;
}


#undef LOCTEXT_NAMESPACE
